﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;

namespace WpfTreeGridTest
{
    public static class SelectedDataLayerSynchronizer
    {
        private static readonly Dictionary<int, bool>
            _layerVisiableStatus = new Dictionary<int, bool>() { { 1, true } };

        private static readonly Dictionary<int, List<WeakReference>> _targetElements =
            new Dictionary<int, List<WeakReference>>();

        public static readonly DependencyProperty SelectedLayerProperty =
            DependencyProperty.RegisterAttached("SelectedLayer", typeof(bool),
                typeof(SelectedDataLayerSynchronizer),
                new PropertyMetadata(false, OnSelectedLayerChange));

        public static bool GetSelectedLayer(DependencyObject obj) =>
            (bool)obj.GetValue(SelectedLayerProperty);

        public static void SetSelectedLayer(DependencyObject obj, bool value) =>
            obj.SetValue(SelectedLayerProperty, value);

        private static void OnSelectedLayerChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is FrameworkElement element) || !(e.NewValue is bool status)) return;
            var index = GetLayer(element);
            if (index <= 0) return;

            if (status)
            {
                var keys = _layerVisiableStatus.Where(m => m.Value)
                    .Select(m => m.Key).ToArray();
                for (int i = 0; i < keys.Length; i++)
                {
                    _layerVisiableStatus[keys[i]] = false;
                    UpdateTargetsForIndex(keys[i]);
                }
            }

            _layerVisiableStatus[index] = status;
            UpdateTargetsForIndex(index);
        }

        public static readonly DependencyProperty LayerProperty =
            DependencyProperty.RegisterAttached("Layer", typeof(int), typeof(SelectedDataLayerSynchronizer),
                new PropertyMetadata(0));

        public static int GetLayer(DependencyObject obj) => (int)obj.GetValue(LayerProperty);

        public static void SetLayer(DependencyObject obj, int value) =>
            obj.SetValue(LayerProperty, value);

        public static readonly DependencyProperty TargetLayerProperty =
            DependencyProperty.RegisterAttached("TargetLayer", typeof(int), typeof(SelectedDataLayerSynchronizer),
                new PropertyMetadata(0, OnTargetLayerChanged));

        public static int GetTargetLayer(DependencyObject obj) => (int)obj.GetValue(TargetLayerProperty);
        public static void SetTargetLayer(DependencyObject obj, int value) => obj.SetValue(TargetLayerProperty, value);

        private static void OnTargetLayerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is FrameworkElement element)) return;
            var oldIndex = (int)e.OldValue;
            var newIndex = (int)e.NewValue;

            // 从旧索引中移除
            if (oldIndex > 0 && _targetElements.TryGetValue(oldIndex, out var targetElement))
            {
                targetElement.RemoveAll(wr =>
                    !wr.IsAlive || Equals(wr.Target, element));
            }

            // 添加到新索引
            if (newIndex > 0)
            {
                if (!_targetElements.ContainsKey(newIndex))
                {
                    _targetElements[newIndex] = new List<WeakReference>();
                }

                // 检查是否已存在引用
                if (!_targetElements[newIndex].Any(wr =>
                        wr.IsAlive && Equals(wr.Target, element)))
                {
                    _targetElements[newIndex].Add(new WeakReference(element));
                }

                // 更新元素宽度
                UpdateElementVisiableStatus(element, newIndex);
            }
        }

        private static void UpdateTargetsForIndex(int index)
        {
            if (!_targetElements.TryGetValue(index, out var references)) return;
            // 清理无效引用
            references.RemoveAll(wr => !wr.IsAlive);

            foreach (var weakRef in references.ToList())
            {
                if (weakRef.IsAlive && weakRef.Target is FrameworkElement element)
                {
                    UpdateElementVisiableStatus(element, index);
                }
            }

            // 如果列表为空，移除该索引
            if (references.Count == 0)
            {
                _targetElements.Remove(index);
            }
        }

        private static void UpdateElementVisiableStatus(FrameworkElement element, int index)
        {
            if (_layerVisiableStatus.TryGetValue(index, out var status))
            {
                element.Visibility = status
                    ? Visibility.Visible
                    : Visibility.Hidden;
            }
            else
            {
                element.Visibility = Visibility.Hidden;
            }
        }
    }
}